////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//                                                                                                                            //
//                                                         WNProject                                                          //
//                                                                                                                            //
//            This file is distributed under the BSD 2-Clause open source license. See License.txt for details.               //
//                                                                                                                            //
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#ifndef __WN_SEMAPHORE_H__
#define __WN_SEMAPHORE_H__

#include "WNCore/inc/WNBase.h"

#ifdef _WN_WINDOWS
    #include <windows.h>

    typedef HANDLE WN_SEMAPHORE_T;
#elif defined _WN_LINUX
    #include <semaphore.h>

    typedef sem_t WN_SEMAPHORE_T;
#endif

__WN_INLINE WN_VOID WNSemaphoreInitialize(WN_SEMAPHORE_T* _semaphore);
__WN_INLINE WN_VOID WNSemaphoreDestroy(WN_SEMAPHORE_T* _semaphore);
__WN_INLINE WN_VOID WNSemaphoreWait(WN_SEMAPHORE_T* _semaphore);
__WN_INLINE WN_VOID WNSemaphorePost(WN_SEMAPHORE_T* _semaphore);

#ifdef _WN_CPLUSPLUS
    class WNMutexScopeLock;

    class WNSemaphore {
    public:
        __WN_INLINE WNSemaphore();
        __WN_INLINE ~WNSemaphore();

        __WN_INLINE WN_VOID Wait();
        __WN_INLINE WN_VOID Post();

    private:
        friend class WNSemaphoreScopeLock;

    private:
        WN_SEMAPHORE_T mSemaphore;
    };

    class WNSemaphoreScopeLock {
    public:
        __WN_INLINE WNSemaphoreScopeLock(WN_SEMAPHORE_T* _semaphore);
        __WN_INLINE WNSemaphoreScopeLock(WNSemaphore& _semaphore);
        __WN_INLINE ~WNSemaphoreScopeLock();

    private:
        WNSemaphoreScopeLock() {}

    private:
        WN_SEMAPHORE_T* mSemaphore;
    };

    #define WN_SEMAPHORE_SCOPE_LOCK(_semaphore) WNSemaphoreScopeLock lock__COUNTER____LINE__(_semaphore)
#endif

#include "WNConcurrency/inc/WNSemaphore.inl"

#endif // __WN_SEMAPHORE_H__